﻿using System;
using RpcClient;
using RpcHelper;
using RpcModel;
using Wedonek.RpcStore.Gateway.Interface;
using Wedonek.RpcStore.Gateway.Model;
using Wedonek.RpcStore.Service.Interface;
using Wedonek.RpcStore.Service.Model;

namespace Wedonek.RpcStore.Gateway.Service
{
    internal class TransactionService : ITransactionService
    {
        private readonly ITransactionCollect _Transaction;
        private readonly IServerTypeCollect _ServerType;
        private readonly IServerCollect _Server;
        public TransactionService(ITransactionCollect transaction,
                IServerCollect server,
                IServerTypeCollect serverType)
        {
            this._Server = server;
            this._ServerType = serverType;
            this._Transaction = transaction;
        }

        public TransactionInfo Get(Guid id)
        {
            TransactionInfo tran = this._Transaction.Get(id);
            if (tran == null)
            {
                throw new ErrorException("rpc.transaction.not.find");
            }
            return tran;
        }

        public TransactionDatum[] GetTranNode(Guid rootId)
        {
            BasicTransaction[] trans = this._Transaction.GetTranNode(rootId);
            if (trans == null)
            {
                return null;
            }
            return this._Format(trans);
        }
        private TransactionDatum[] _Format(BasicTransaction[] trans)
        {
            BasicServerType[] types = this._ServerType.GetBasic(trans.Distinct(a => a.SystemType));
            BasicService[] servers = this._Server.GetBasic(trans.Distinct(a => a.ServerId));
            return trans.ConvertMap<BasicTransaction, TransactionDatum>((a, b) =>
           {
               b.SystemName = types.Find(c => c.TypeVal == a.SystemType, c => c.SystemName);
               b.ServerName = servers.Find(c => c.Id == a.ServerId, c => c.ServerName);
               return b;
           });
        }

        public TransactionDatum[] QueryRoot(RootQueryParam query, IBasicPage paging, out long count)
        {
            BasicTransaction[] trans = this._Transaction.QueryRoot(query, paging, out count);
            if (trans == null)
            {
                return null;
            }
            return this._Format(trans);
        }
        public TransactionTree[] QueryTree(RootQueryParam query, IBasicPage paging, out long count)
        {
            BasicTransaction[] trans = this._Transaction.QueryRoot(query, paging, out count);
            if (trans == null)
            {
                return null;
            }
            BasicTransaction[] list = this._Transaction.GetTranNodes(trans.ConvertAll(a => a.Id));
            BasicTransaction[] all = list.Add(trans);
            BasicServerType[] types = this._ServerType.GetBasic(all.Distinct(a => a.SystemType));
            BasicService[] servers = this._Server.GetBasic(all.Distinct(a => a.ServerId));
            return trans.ConvertMap<BasicTransaction, TransactionTree>((a, b) =>
           {
               this._InitTree(a, b, list, types, servers);
               return b;
           });
        }
        private void _InitTree(BasicTransaction tran, TransactionTree tree, BasicTransaction[] list, BasicServerType[] types, BasicService[] servers)
        {
            tree.SystemName = types.Find(c => c.TypeVal == tran.SystemType, c => c.SystemName);
            tree.ServerName = servers.Find(c => c.Id == tran.ServerId, c => c.ServerName);
            tree.Childrens = this._GetTrees(tree, list, types, servers);
        }
        private TransactionTree[] _GetTrees(TransactionTree tran, BasicTransaction[] list, BasicServerType[] types, BasicService[] servers)
        {
            return list.ConvertMap<BasicTransaction, TransactionTree>(a => a.ParentId == tran.Id && a.Id != tran.Id, (a, b) =>
           {
               this._InitTree(a, b, list, types, servers);
               return b;
           });
        }
    }
}
